package com.jt.www.admin.order_pc.service.impl;

import com.alibaba.fastjson.JSON;
import com.jt.www.admin.market.service.CommissionService;
import com.jt.www.admin.order_pc.service.OfflineEndorseService;
import com.jt.www.dao.mapper.offline.OfflineEndorseMapper;
import com.jt.www.dao.mapper.offline.OfflineMapper;
import com.jt.www.domain.bo.OfflineEndorseBO;
import com.jt.www.domain.dto.AttachmentsDto;
import com.jt.www.domain.dto.EndorsementDto;
import com.jt.www.domain.dto.EndorsementOrderDto;
import com.jt.www.domain.enums.common.*;
import com.jt.www.domain.po.OfflineEndorse;
import com.jt.www.domain.qo.OfflineEndorseQO;
import com.jt.www.domain.vo.*;
import com.jt.www.model.issue.InsuranceCompanyVO;
import com.jt.www.model.reps.GenericDataResponse;
import com.jt.www.model.reps.GenericListResponse;
import com.jt.www.model.vo.sdCheck.InsuredForProVO;
import com.jt.www.remote.BmsClient;
import com.jt.www.remote.PolClient;
import com.jt.www.remote.SttlManClient;
import com.jt.www.remote.ins.InsClient;
import com.jt.www.util.DateUtils;
import com.jt.www.util.JsonUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.weekend.Weekend;
import tk.mybatis.mapper.weekend.WeekendCriteria;

import java.util.*;

import static com.jt.www.util.DateUtils.*;

/**
 * 线下录单 批单
 * Created by shaoyn on 2020/05/25.
 */
@Service
public class OfflineEndorseSeviceImpl implements OfflineEndorseService {

    public static final Logger log = LoggerFactory.getLogger(OfflineEndorseSeviceImpl.class);

    @Autowired
    private OfflineEndorseMapper offlineEndorseMapper;
    @Autowired
    private OfflineMapper offlineMapper;
    @Autowired
    private PolClient polClient;
    @Autowired
    private InsClient insClient;
    @Autowired
    private CommissionService commissionService;

    @Autowired
    private SttlManClient sttlManClient;

    @Autowired
    private BmsClient bmsClient;

    @Override
    public int saveOfflineEndorse(OfflineEndorse offlineEndorse) {
        //录入时间
        offlineEndorse.setInputTime(new Date());
        return offlineEndorseMapper.insertSelective(offlineEndorse);
    }

    @Override
    public boolean isExistent(String findCode, String endorseNo) {

        log.info("{} 查询教育线下批单是否存在该批单号{}。", findCode, endorseNo);

        Weekend<OfflineEndorse> weekend = new Weekend<>(OfflineEndorse.class);
        WeekendCriteria<OfflineEndorse, Object> criteria = weekend.weekendCriteria();
        criteria.andNotEqualTo(OfflineEndorse::getPushStatus, PushStatusEnum.ERROR.getCode());
        criteria.andEqualTo(OfflineEndorse::getEndorseNo, endorseNo);
        criteria.andEqualTo(OfflineEndorse::getIsDeleted, IsDeletedEnum.NO.getValue());
        //查询本地
        if (offlineEndorseMapper.selectCountByExample(weekend) != 0) {
            log.info("{} 通过批单号{} 查询到教育中存在“推送状态”不为推送失败的线下批单。", findCode, endorseNo);
            return true;
        }
        log.info("{} 通过批单号{}未查询到教育线下批单。", findCode, endorseNo);
        try {
            GenericDataResponse<Map<String, Integer>> ret = polClient.validEndorsementsNoUniq(endorseNo, "edu");
            log.info("{} 通过批单号{}查询保单服务中心出参。", findCode, JSON.toJSONString(ret));
            if (ret != null && GenericDataResponse.CODE_OK.equals(ret.getCode())
                    && null != ret.getData().get("size")
                    && ret.getData().get("size") > 0) {
                return true;
            }
        } catch (Exception e) {
            log.info("{} 通过批单号{}查询批单中心异常。", findCode, endorseNo);
        }
        return false;
    }

    /**
     *  查询批单出单日期是否跨期
     * @param findCode
     * @param endorseNo
     * @param endorseIssueDate
     * @return
     */
    @Override
    public boolean isIntertemporal(String findCode, String endorseNo,Date endorseIssueDate)throws Exception {
        //判断当前日期和签单日期是否在同一月份
        if (!DateUtils.isSameMonth(new Date(), endorseIssueDate)) {
            //不同月份跨期,调用业管
            //拿签单时间去查询业管系统，查出来跨期
            GenericListResponse intertermporalDate = getIntertemporal(endorseIssueDate);
            if(intertermporalDate.getList()!=null){
                //拿当前时间也就是录单时间，在业管返回的期间内，判断，如果在就不是跨期，如果不在就跨期
                if (!isEffectiveDate(format_date_format_yyyy_mm_dd.parse(getCurrentDay()),  DateUtils.strToDate((String)((LinkedHashMap) intertermporalDate.getList().get(0)).get("fperiodStart")),
                        DateUtils.strToDate((String) ((LinkedHashMap) intertermporalDate.getList().get(0)).get("fperiodEnd")))) {
                    return true;

                }
            }

        }
        return false;
    }

    public GenericListResponse getIntertemporal(Date insureDate) throws Exception {
        String fperiod = DateUtils.converDateYm(insureDate);
        GenericListResponse intertermporalDate = bmsClient.getIntertemporal(fperiod);
        return intertermporalDate;
    }

    @Override
    public ResponseEntity<GenericListResponse<OfflineEndorse>> queryOfflineEndorse(OfflineEndorseQO offlineEndorseQO) {

        //查询总条数
        Long count = offlineMapper.queryOfflineEndorseCount(offlineEndorseQO);
        if (null == count || count <= 0) {
            return GenericListResponse.listNoCount(null);
        }
        List<OfflineEndorse> offlineEndorses = offlineMapper.queryOfflineEndorse(offlineEndorseQO);
        return GenericListResponse.listAndCount(offlineEndorses, count);
    }

    @Override
    public ResponseEntity<GenericDataResponse<OfflineEndorseBO>> queryOfflineEndorseDetails(Long EndorseId) {

        OfflineEndorse offlineEndorse = offlineEndorseMapper.selectByPrimaryKey(EndorseId);
        if (null == offlineEndorse) {
            return GenericDataResponse.errorWithMsg("无查询数据", OfflineEndorseBO.class);
        }
        OfflineEndorsePolicyVo offlineEndorsePolicyVo = queryPolicyByPolicyNo(offlineEndorse.getPolicyNo());
        return GenericDataResponse.okWithData(new OfflineEndorseBO(offlineEndorsePolicyVo, offlineEndorse));
    }

    @Override
    public int updateOfflineEndorse(OfflineEndorse offlineEndorse) throws Exception {
        if (null == offlineEndorse.getId()) {
            return 0;
        }
        offlineEndorse.setUpdateTime(new Date());
        //录入时间
        offlineEndorse.setInputTime(new Date());
        //需要判断是否跨期，如果重新修改了签单日期，需要再次判断
        if (!DateUtils.isSameMonth(new Date(), offlineEndorse.getInsureDate())) {
            //不同月份跨期,调用业管
            //拿签单时间去查询业管系统，查出来跨期
            GenericListResponse intertermporalDate = getIntertemporal(offlineEndorse.getInsureDate());
            if(intertermporalDate.getList()!=null){
                //拿当前时间也就是录单时间，在业管返回的期间内，判断，如果在就不是跨期，如果不在就跨期
                if (!isEffectiveDate(format_date_format_yyyy_mm_dd.parse(getCurrentDay()), DateUtils.strToDate((String)((LinkedHashMap) intertermporalDate.getList().get(0)).get("fperiodStart")),
                        DateUtils.strToDate((String) ((LinkedHashMap) intertermporalDate.getList().get(0)).get("fperiodEnd")))) {
                    offlineEndorse.setCrossTerm(IsOrNotEnum.IS.getValue());

                }else{
                    offlineEndorse.setCrossTerm(IsOrNotEnum.NO.getValue());
                }
            }else{
                offlineEndorse.setCrossTerm(IsOrNotEnum.NO.getValue());
            }

        }
        return offlineEndorseMapper.updateByPrimaryKeySelective(offlineEndorse);
    }

    @Override
    public ResponseEntity auditOfflineEndorse(String findCode, OfflineEndorse offlineEndorse) {
        ResponseEntity responseEntity = GenericDataResponse.ok();
        OfflineEndorse newOfflineEndorse = new OfflineEndorse();
        newOfflineEndorse.setAuditTime(new Date());
        newOfflineEndorse.setUpdateTime(new Date());
        newOfflineEndorse.setId(offlineEndorse.getId());
        newOfflineEndorse.setAuditStatus(offlineEndorse.getAuditStatus());
        newOfflineEndorse.setAuditOpinion(offlineEndorse.getAuditOpinion());
        //如果是审核通过  需要做线下推送到投保中心
        if (AuditStatusEnum.SUCCESS.getCode().equals(offlineEndorse.getAuditStatus())) {
            OfflineEndorse oldOfflineEndorse = offlineEndorseMapper.selectByPrimaryKey(offlineEndorse.getId());
            if (oldOfflineEndorse.getAuditStatus().equals(AuditStatusEnum.SUCCESS.getCode())) {
                log.info("{} 该ID已经为审核通过状态，不需要再次审核!", findCode);
                return GenericDataResponse.errorWithMsg("已经为审核通过状态，不需要再次审核!");
            }
            //推送批单信息到保单服务中心
            try {
                pushEndorseToPol(findCode, offlineEndorse.getId());
            } catch (Exception e) {
                newOfflineEndorse.setPushStatus(PushStatusEnum.ERROR.getCode());
                newOfflineEndorse.setErrorMsg(e.getMessage());
                responseEntity = GenericDataResponse.errorWithMsg(e.getMessage());
            }
        }
        offlineEndorseMapper.updateByPrimaryKeySelective(newOfflineEndorse);
        return responseEntity;
    }

    @Override
    public OfflineEndorsePolicyVo queryPolicyByPolicyNo(String policyNo) {
        try {
            //第一步先看投保中心是否有投保单
            GenericDataResponse<PolicyDetailVO> response = insClient.policyDetail(policyNo);

            if (response != null && response.getCode().equals(GenericDataResponse.CODE_OK)) {
                PolicyDetailVO policyDetailVO = response.getData();
                OfflineEndorsePolicyVo offlineEndorsePolicyVo = new OfflineEndorsePolicyVo();
                offlineEndorsePolicyVo.setAppCode(policyDetailVO.getAppCode());
                offlineEndorsePolicyVo.setBranchCode(policyDetailVO.getBranchCode());
                offlineEndorsePolicyVo.setBranchName(policyDetailVO.getBranchName());
                List<InsuranceCompanyVO> insuranceCompanyVOS = policyDetailVO.getInsuranceCompanyVOS();
                for (InsuranceCompanyVO insuranceCompanyVO : insuranceCompanyVOS) {
                    //主承
                    if (insuranceCompanyVO.getRole2().equals("01")) {
                        offlineEndorsePolicyVo.setInsCompanyCode(insuranceCompanyVO.getCode());
                        offlineEndorsePolicyVo.setInsCompanyName(insuranceCompanyVO.getName());
                        break;
                    }
                }
                offlineEndorsePolicyVo.setProductCode(policyDetailVO.getProductCode());
                offlineEndorsePolicyVo.setProductName(policyDetailVO.getProductName());
                offlineEndorsePolicyVo.setPolicyNo(policyNo);
                offlineEndorsePolicyVo.setHolderCode(policyDetailVO.getHolder().getHolderCode());
                if (null != policyDetailVO.getHolder().getCorporation()) {
                    offlineEndorsePolicyVo.setHolderName(policyDetailVO.getHolder().getCorporation().getName());
                } else if (null != policyDetailVO.getHolder().getHuman()) {
                    offlineEndorsePolicyVo.setHolderName(policyDetailVO.getHolder().getHuman().getName());
                }

                List<InsuredForProVO> insuredList = policyDetailVO.getInsuredList();
                if (CollectionUtils.isNotEmpty(insuredList) && null != insuredList.get(0).getCorporation()) {
                    offlineEndorsePolicyVo.setInsuredName(insuredList.get(0).getCorporation().getName());
                } else if (CollectionUtils.isNotEmpty(insuredList) && null != insuredList.get(0).getHuman()) {
                    offlineEndorsePolicyVo.setInsuredName(insuredList.get(0).getHuman().getName());
                }
                offlineEndorsePolicyVo.setStartDate(policyDetailVO.getPolStartDate());
                offlineEndorsePolicyVo.setEndDate(policyDetailVO.getPolEndDate());
                offlineEndorsePolicyVo.setInsureDate(policyDetailVO.getIssueDate());
                offlineEndorsePolicyVo.setPremium(policyDetailVO.getPremium());
                return offlineEndorsePolicyVo;
            }
        } catch (Exception e) {
            log.error("保单查询失败");
        }

        return null;
    }

    @Override
    public ResponseEntity deleteEndorse(Long id) {
        OfflineEndorse offlineEndorse = offlineEndorseMapper.selectByPrimaryKey(id);
        if (null == offlineEndorse || IsDeletedEnum.is(offlineEndorse.getIsDeleted())) {
            return GenericDataResponse.errorWithMsg("该批单申请不存在!");
        }
        if (!AuditStatusEnum.BACK.getCode().equals(offlineEndorse.getAuditStatus())) {
            return GenericDataResponse.errorWithMsg("该批单申请非回退状态不能删除!");
        }

        //删除订单信息
        OfflineEndorse updateEndorse = new OfflineEndorse();
        updateEndorse.setId(id);
        updateEndorse.setIsDeleted(IsDeletedEnum.IS.getValue());
        int n = offlineEndorseMapper.updateByPrimaryKeySelective(updateEndorse);

        if (n > 0) {
            return GenericDataResponse.ok();
        }
        return GenericDataResponse.errorWithMsg("该批单申请删除失败!");
    }

    /**
     * 查询批单详情
     *
     * @return
     */
    private PolEndorsementsInfoVO getPolEndorsementsInfoVOByPolicyNo(String policyNo) throws Exception {
        GenericDataResponse<PolQueryForProDetailVO> response = polClient.queryLiabilityPolDetail(policyNo);
        if (null == response) {
            throw new Exception("查询保单" + policyNo + "信息异常");
        }
        if (null == response.getData()) {
            return null;
        }
        return response.getData().getEndorsementsInfo();
    }

    @Override
    public void pushEndorseToPol(String findCode, Long id) throws Exception {
        OfflineEndorse offlineEndorse = offlineEndorseMapper.selectByPrimaryKey(id);
        if (null == offlineEndorse) {
            log.info("{} ID为：{}的线下批单，未查询到批单信息。", findCode, id);
            throw new Exception("该批次号不正确。");
        }
        if (offlineEndorse.getPushStatus().equals(PushStatusEnum.SUCCESS.getCode())) {
            log.info("{} ID为：{}的线下批单，推送状态为已推送。", findCode, id);
            throw new Exception("该批次号对应的线下批量推送状态为已推送，不需要再次推送。");
        }

        OfflineEndorsePolicyVo offlineEndorsePolicyVo = queryPolicyByPolicyNo(offlineEndorse.getPolicyNo());
        if (offlineEndorsePolicyVo == null) {
            log.info("{}ID为：{}的线下批单，保单号：{}，未查询到保单信息。", findCode, id, offlineEndorsePolicyVo.getPolicyNo());
            throw new Exception("该保单不存在，不能做批单。");
        }

        //线下批单order对象
        EndorsementOrderDto endorsementOrderDto = new EndorsementOrderDto();
        endorsementOrderDto.setEntryType("00");
        endorsementOrderDto.setKind("A2");
        endorsementOrderDto.setSource("00");
        endorsementOrderDto.setOperator(offlineEndorse.getOperatorNo());
        endorsementOrderDto.setOperatorName(offlineEndorse.getOperatorName());
        EndorsementDto endorsement = new EndorsementDto();

        endorsement.setEndorsementsNo(offlineEndorse.getEndorseNo());
        endorsement.setEndorsementsType(offlineEndorse.getEndorseType());
        endorsement.setEndorsementMode("02");
        endorsement.setPolicyPremium(offlineEndorsePolicyVo.getPremium());
        endorsement.setAppCode(offlineEndorsePolicyVo.getAppCode());
        endorsement.setInsuranceNo(offlineEndorse.getPolicyNo());
        endorsement.setBatchPremium(offlineEndorse.getPremium());
        endorsement.setProductCode(offlineEndorsePolicyVo.getProductCode());
        endorsement.setProductName(offlineEndorsePolicyVo.getProductName());
        endorsement.setProductType("00");
        endorsement.setChannelCode("edu");
        endorsement.setChannelName("教保网渠道");
        endorsement.setReason("线下录入");
        endorsement.setStartDate(offlineEndorse.getStartDate());
        endorsement.setEndDate(offlineEndorse.getEndDate());
        endorsement.setValidDate(offlineEndorse.getStartDate());
        endorsement.setIssueDate(offlineEndorse.getInsureDate());

        //投保人编码
        endorsement.setApplicantCode(offlineEndorsePolicyVo.getHolderCode());
        endorsement.setApplicant(offlineEndorsePolicyVo.getHolderName());
        endorsement.setBranchCode(offlineEndorsePolicyVo.getBranchCode());
        endorsement.setBranchName(offlineEndorsePolicyVo.getBranchName());
        //设置认领信息
        createContextClaim(endorsement,offlineEndorse);
        //保费变动前后金额  需要从批单中心查询 之后计算
        PolEndorsementsInfoVO polEndorsementsInfoVO = getPolEndorsementsInfoVOByPolicyNo(offlineEndorse.getPolicyNo());
        log.info("{}ID为：{}的线下批单，通过保单号{}，查询保单中心出参：{}", findCode, id, offlineEndorse.getPolicyNo(), JSON.toJSONString(polEndorsementsInfoVO));
        if (null == polEndorsementsInfoVO) {
            //如果没有保单信息 使用投保单金额
            endorsement.setPremiumAmountBefore(offlineEndorsePolicyVo.getPremium());
            endorsement.setPremiumAmountAfter(offlineEndorsePolicyVo.getPremium().add(offlineEndorse.getPremium()));
        } else {
            //如果有保单信息 使用保单变更后金额
            endorsement.setPremiumAmountBefore(polEndorsementsInfoVO.getPremiumAmountAfter());
            endorsement.setPremiumAmountAfter(polEndorsementsInfoVO.getPremiumAmountAfter().add(offlineEndorse.getPremium()));
        }

        List<AttachmentsDto> attachments = Lists.newArrayList();
        if (StringUtils.isNotBlank(offlineEndorse.getAttachedFile())) {
            try {
                List<FileVO> fileVOS = JSON.parseArray(offlineEndorse.getAttachedFile(), FileVO.class);
                for (FileVO fileVO : fileVOS) {
                    AttachmentsDto attachmentsDto = new AttachmentsDto(fileVO.getFileName(), fileVO.getFileId(), fileVO.getFileType());
                    attachments.add(attachmentsDto);
                }
            } catch (Exception e) {
                log.error("{}批单号为{}的线下投批单，附件Json格式不正确!", findCode, offlineEndorse.getEndorseNo());
                throw new Exception("附件Json格式不正确!");
            }
        }
        endorsement.setAttachments(attachments);
        endorsementOrderDto.setEndorsements(Lists.newArrayList(endorsement));
        log.info("{}ID为：{}的线下批单，下发到保单中心入参：{}", findCode, id, JsonUtil.object2Json(endorsementOrderDto));
        GenericDataResponse<Map> result = polClient.submitEndors(JsonUtil.object2Json(endorsementOrderDto));
        log.info("{}ID为：{}的线下批单，下发到保单中心出参：{}", findCode, id, JsonUtil.object2Json(result));
        if (result.getCode().equals(GenericDataResponse.CODE_NG)) {
            throw new Exception(result.getMsg());
        }
        String applyNo = ((List<String>) result.getData().get("applyNos")).get(0);
        if (StringUtils.isBlank(applyNo)) {
            throw new Exception("批单申请号返回异常");

        }
        //修改推送成功状态
        OfflineEndorse update = new OfflineEndorse();
        update.setId(id);
        update.setPushStatus(PushStatusEnum.SUCCESS.getCode());
        offlineEndorseMapper.updateByPrimaryKeySelective(update);

        //批单计算佣金业绩
        commissionService.createPolCommissionPush(findCode, applyNo, endorsement.getEndorsementsNo(), offlineEndorse.getOperatorNo());
    }

    private EndorsementDto createContextClaim(EndorsementDto endorsementDto,OfflineEndorse offlineEndorse) {
        //查询到该保单是否跨期
        if(offlineEndorse.getCrossTerm().equals(IsOrNotEnum.IS.getValue())){
            // 收入确认时间点
            if(offlineEndorse.getIncomeConfirmTime() !=null){
                endorsementDto.setRevenueRecognitionTime(offlineEndorse.getIncomeConfirmTime());
            }
            //  收入确认佐证原因
            if(offlineEndorse.getEvidenceReason() !=null){
                endorsementDto.setRevenueRecognitionReason(EvidenceReasonEnum.getDescByCode(offlineEndorse.getEvidenceReason()));
            }

            //revenueRecognitionOtherReason收入确认佐证其他原因
            if(offlineEndorse.getOtherReason() !=null){
                endorsementDto.setRevenueRecognitionOtherReason(offlineEndorse.getOtherReason());
            }
        }
        //revenueRecognitionFile 收入确认佐证文件
        if(offlineEndorse.getEvidenceFile() !=null){
            List<AttachmentsDto> attachmentVOS = new ArrayList<>(5);
            List<FileVO> policyFile;
            policyFile = JSON.parseArray(offlineEndorse.getEvidenceFile(), FileVO.class);
            for (int i = 0; i < policyFile.size(); i++) {
                AttachmentsDto attachmentVO = new AttachmentsDto();
                attachmentVO.setId(policyFile.get(i).getFileId());
                attachmentVO.setType(BusinessTypeCodeEnum.F005.getCode());
                attachmentVOS.add(attachmentVO);
            }
            endorsementDto.setAttachments(attachmentVOS);
        }
        return endorsementDto;
    }
}
